package cn.yulr.http;

import org.apache._http.HttpException;
import org.apache._http.HttpRequest;
import org.apache._http.HttpResponse;
import org.apache._http.nio.protocol.*;
import org.apache._http.protocol.HttpContext;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * http请求将通过此部分来实现回调
 * 同时此部分用来注册 aciton 信息
 * 此部分主要处理 HttpRequest 部分
 */
public class HttpRequestAsyncRequestHander extends MHttpAsyncRequestHandler {

    public HttpRequestAsyncRequestHander(String requestAction) {
        super(requestAction);
    }

    @Override
    public HttpAsyncRequestConsumer<HttpRequest> processRequest(HttpRequest request, HttpContext context) throws HttpException, IOException {
        return new BasicAsyncRequestConsumer();
    }

    //region 回调注册部分
    private final List<HttpRequestActionListener> httpRequestActionListenerList = new CopyOnWriteArrayList<>();

    public void addHttpRequestActionFinishedListener(HttpRequestActionListener httpRequestActionListener) {
        if (httpRequestActionListener == null) return;
        synchronized (httpRequestActionListenerList) {
            httpRequestActionListenerList.add(httpRequestActionListener);
        }
    }

    public void removeHttpRequestActionFinishedListener(HttpRequestActionListener httpRequestActionListener) {
        if (httpRequestActionListener == null) return;
        synchronized (httpRequestActionListenerList) {
            httpRequestActionListenerList.remove(httpRequestActionListener);
        }
    }
    //endregion

    /**
     * 实际处理方法
     *
     * @param data         request data returned by the request consumer.
     * @param httpExchange HTTP exchange.
     * @param context      HTTP execution context.
     */
    @Override
    public void handle(Object data, HttpAsyncExchange httpExchange, HttpContext context) throws HttpException, IOException {
        HttpResponse response = httpExchange.getResponse();
        boolean isNeedHandleInternal = false;
        synchronized (httpRequestActionListenerList) {
            if (httpRequestActionListenerList.size() > 0) {
                for (HttpRequestActionListener httpRequestActionListener : httpRequestActionListenerList) {
                    if (httpRequestActionListener.onHttpRequestAction(super.requestAction, (HttpRequest) data, response, context)) {
                        isNeedHandleInternal = true;
                    }
                }
            }
        }

        /**
         * 如果上层有返回 true 的情况，则不需要下层执行处理操作
         */
        if (!isNeedHandleInternal) {
            handleInternal((HttpRequest) data, response, context);
        }

        synchronized (httpRequestActionListenerList) {
            if (httpRequestActionListenerList.size() > 0) {
                for (HttpRequestActionListener httpRequestActionListener : httpRequestActionListenerList) {
                    httpRequestActionListener.onHttpRequestActionPreSend(super.requestAction, (HttpRequest) data, response, context);
                }
            }
        }

        httpExchange.submitResponse(new BasicAsyncResponseProducer(response));

        synchronized (httpRequestActionListenerList) {
            if (httpRequestActionListenerList.size() > 0) {
                for (HttpRequestActionListener httpRequestActionListener : httpRequestActionListenerList) {
                    httpRequestActionListener.onHttpRequestActionFinished(super.requestAction, (HttpRequest) data, response, context);
                }
            }
        }
    }

    /**
     * 实际上层的处理方法
     * 此部分需要重写，基于 request 和 response 来实现数据交换
     *
     * @param request  请求内容
     * @param response 响应内容
     * @param context  上下文相关数据，此部分暂时不使用，用于处理 Session 和 全局信息
     */
    public void handleInternal(final HttpRequest request,
                               final HttpResponse response,
                               final HttpContext context) throws HttpException, IOException {

    }

}
